package com.rzjm.exercise.sys.core.dict.aspect;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.rzjm.exercise.common.base.data.DataTable;
import com.rzjm.exercise.common.utils.CollectionUtils;
import com.rzjm.exercise.common.utils.ReflectionUtils;
import com.rzjm.exercise.common.utils.StringUtils;
import com.rzjm.exercise.sys.core.dict.annotation.DictCode;
import com.rzjm.exercise.sys.core.dict.domain.DictDO;
import com.rzjm.exercise.sys.core.dict.service.DictService;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

@Aspect
@Component
public class DictAspect {
	@Resource
	private DictService dictService;

    @Pointcut("@annotation(com.rzjm.exercise.sys.core.dict.annotation.DictBody)")
    public void logPointCut() {
    }

    @AfterReturning(returning = "result", pointcut = "logPointCut()")
    public void doAfterReturning(Object result) throws Throwable {
		List<?> list = null;

    	if (List.class.isAssignableFrom(result.getClass())) {
    		list = (List<?>) result;
    	} else if (DataTable.class.isAssignableFrom(result.getClass())) {
    		list = ((DataTable<?>) result).getRows();
    	} else {
    		list = Arrays.asList(result);
    	}

    	if (CollectionUtils.isEmpty(list)) {
    		return;
    	}

    	Map<String, Map<String, String>> dictMap = new HashMap<>();

    	Class<?> searchType = list.get(0).getClass();

		while (searchType != null) {
			for (Field field : searchType.getDeclaredFields()) {
    			if (field.isAnnotationPresent(DictCode.class)) {
    				DictCode dictCode = field.getAnnotation(DictCode.class);
    				List<DictDO> dictList = dictService.findByType(dictCode.value());

    				if (!CollectionUtils.isEmpty(dictList)) {
    					dictMap.put(field.getName(), dictList.stream().collect(Collectors.toMap(DictDO::getValue, DictDO::getName,(e1, e2) -> e1)));
    				}
    			}
    		}

			searchType = searchType.getSuperclass();
		}

		if (CollectionUtils.isEmpty(dictMap)) {
			return;
		}

		list.stream().forEach((type) -> {
			dictMap.forEach((field, map) -> {
				Object value = ReflectionUtils.get(type, field);

				if (value != null) {
					List<String> values = Arrays.stream(StringUtils.split(value.toString(), ","))
							.map((v) -> map.get(v)).collect(Collectors.toList());

					ReflectionUtils.set(type, field, StringUtils.join(values, ","));
				}
			});
		});
    }
}
